package fr.norsys.mapper.console.service;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeSet;

import javax.naming.Context;
import javax.naming.NamingException;
import javax.naming.directory.DirContext;
import javax.naming.directory.InitialDirContext;

import net.sf.navigator.menu.MenuComponent;
import net.sf.navigator.menu.MenuRepository;

import org.apache.commons.lang.StringUtils;

import fr.norsys.mapper.console.model.Connection;
import fr.norsys.mapper.console.utils.URLEncoderUtil;

public class LdapTreeBuilderImpl implements LdapTreeBuilder {
	private LDAPViewer ldapViewer;

	private String root;

	private Map config;

	public LDAPViewer getLdapViewer() {
		return ldapViewer;
	}

	public void setLdapViewer(LDAPViewer ldapViewer) {
		this.ldapViewer = ldapViewer;
	}

	public void setConnection(Connection connection) {
		config = new HashMap();
		config.put(Context.INITIAL_CONTEXT_FACTORY,
				"com.sun.jndi.ldap.LdapCtxFactory");
		if (connection.getUrl() != null) {
			config.put(Context.PROVIDER_URL, connection.getUrl());
		}
		if (connection.getUser() != null) {
			config.put(Context.SECURITY_PRINCIPAL, connection.getUser());
		}
		if (connection.getPass() != null) {
			config.put(Context.SECURITY_CREDENTIALS, connection.getPass());
		}
	}

	public boolean isAttributeMandatory(String ldapAttribute, String root) {
		DirContext ctx = null;
		boolean b = false;
		try {
			ctx = new InitialDirContext(new Hashtable(config));
			ldapViewer.setContext(ctx);
			b = ldapViewer.getMandatoryAttributes(root).contains(ldapAttribute);
		} catch (NamingException e) {
		} finally {
			if (ctx != null) {
				try {
					ctx.close();
				} catch (NamingException e) {
				}
			}
		}
		return b;
	}

	public Set getMandatoryAttributes(String root) {
		DirContext ctx = null;
		Set s = null;
		try {
			ctx = new InitialDirContext(new Hashtable(config));
			ldapViewer.setContext(ctx);
			s = ldapViewer.getMandatoryAttributes(root);
		} catch (NamingException e) {
		} finally {
			if (ctx != null) {
				try {
					ctx.close();
				} catch (NamingException e) {
				}
			}
		}
		return s;
	}
	public Set getAllAttributes(String root) {
		DirContext ctx = null;
		Set s = null;
		try {
			ctx = new InitialDirContext(new Hashtable(config));
			ldapViewer.setContext(ctx);
			s = ldapViewer.getAllAttributes(root);
		} catch (NamingException e) {
		} finally {
			if (ctx != null) {
				try {
					ctx.close();
				} catch (NamingException e) {
				}
			}
		}
		return s;
	}

	public MenuRepository buildTree(MenuRepository oldRepository,
			String filter, String contextPath) throws Exception {
		if (filter == null || "".equals(filter.trim())) {
			MenuComponent rootMC = new MenuComponent();
			rootMC.setName(root);
			rootMC.setTitle(root);
			rootMC.setLocation(contextPath
					+ "?method=build&decorator=popup&confirm=true&filter="
					+ URLEncoderUtil.escape(root));
			oldRepository.addMenu(rootMC);
		} else {
			MenuComponent parent = getMenuComponent(oldRepository, filter);
			if (parent != null) {
				List children = getChildren(filter);
				parent.getComponents().clear();
				MenuComponent mc = null;
				for (Iterator it = children.iterator(); it.hasNext();) {
					String name = (String) it.next();
					mc = new MenuComponent();
					mc.setName(name);
					mc.setTitle(name);
					mc.setParent(parent);
					mc
							.setLocation(contextPath
									+ "?method=build&decorator=popup&confirm=true&filter="
									+ URLEncoderUtil.escape(getFullFilter(mc)));
				}
			}
		}
		return oldRepository;
	}

	public List getChildren(String root) {
		List res = null;
		DirContext ctx = null;

/*		if(config == null)
			return new A*/
		try {
			ctx = new InitialDirContext(new Hashtable(config));
			ldapViewer.setContext(ctx);
			res = ldapViewer.getChildElements(root);
		} catch (NamingException e) {
			return new ArrayList();
		} finally {
			if (ctx != null) {
				try {
					ctx.close();
				} catch (NamingException e) {
				}
			}
		}
		return res;
	}

	private MenuComponent getMenuComponent(MenuRepository repository,
			String filter) {
		List l = Arrays.asList(StringUtils.split(filter, ','));
		Collections.reverse(l);
		MenuComponent mc = repository.getMenu(root);
		String[] names = (String[]) l.toArray(new String[l.size()]);
		for (int i = 1; i < names.length; i++) {
			mc = getMenuComponentChild(mc, names[i]);
		}
		return mc;
	}

	private MenuComponent getMenuComponentChild(MenuComponent mc, String name) {
		MenuComponent tmpmc = mc;
		for (Iterator it = mc.getComponents().iterator(); it.hasNext();) {
			tmpmc = (MenuComponent) it.next();
			if (tmpmc.getName().equals(name)) {
				break;
			}
		}
		return tmpmc;
	}

	private String getFullFilter(MenuComponent mc) {
		List l = new ArrayList();
		MenuComponent parent = mc.getParent();
		while (parent != null) {
			String name = parent.getName();
			if (name != null) {
				l.add(name);
			}
			parent = parent.getParent();
		}
		StringBuffer sb = new StringBuffer("");
		if (mc.getName() != null) {
			sb.append(mc.getName());
		}
		for (Iterator it = l.iterator(); it.hasNext();) {
			sb.append(",").append(it.next());
		}
		return sb.toString();
	}

	public String getRoot() {
		return root;
	}

	public void setRoot(String root) {
		this.root = root;
	}

	public Map getConfig() {
		return config;
	}

	public void setConfig(Map config) {
		this.config = config;
	}
}
